Rename gtk-update-icon-cache and gtk-builder-convert back
authorMatthias Clasen <mclasen@redhat.com>
Tue, 4 Jan 2011 02:31:55 +0000 (21:31 -0500)
committerMatthias Clasen <mclasen@redhat.com>
Tue, 4 Jan 2011 02:35:23 +0000 (21:35 -0500)
In bug 635207, it was pointed out that it is a bad idea to
rename these tools purely in the name of parallel-installability,
since it forces dependencies to make a choice between running
gtk-update-icon-cache and gtk-update-icon-cache-3.0 (or both ?!).

So, we rename these utilities back to their un-suffixed names
and rely on distributors to resolve the conflict between GTK+ 2.x
and GTK+ 3.0 packages, which can be done e.g. by dropping the
utilities from the gtk3 packages and add a gtk3 -> gtk2 dependency.

docs/reference/gtk/Makefile.am
docs/reference/gtk/gtk-builder-convert-3.0.xml [deleted file]
docs/reference/gtk/gtk-builder-convert.xml [new file with mode: 0644]
docs/reference/gtk/gtk-docs.sgml
docs/reference/gtk/gtk-update-icon-cache-3.0.xml [deleted file]
docs/reference/gtk/gtk-update-icon-cache.xml [new file with mode: 0644]
gtk/Makefile.am
gtk/gtk-builder-convert [new file with mode: 0755]
gtk/gtk-builder-convert-3.0 [deleted file]
modules/input/Makefile.am

index 9389c0413afa041eed927ae8d10a38df112046ac..959e0b0a5e6f353da2e45a7ec8713485ca5bc5c4 100644 (file)
@@ -134,8 +134,8 @@ content_files =                                     \
        windows.sgml                            \
        x11.sgml                                \
        gtk-query-immodules-3.0.xml             \
-       gtk-update-icon-cache-3.0.xml           \
-       gtk-builder-convert-3.0.xml             \
+       gtk-update-icon-cache.xml               \
+       gtk-builder-convert.xml                 \
        visual_index.xml                        \
        getting_started.xml                     \
        overview.xml
@@ -370,8 +370,8 @@ EXTRA_DIST += version.xml.in
 
 man_MANS =                             \
        gtk-query-immodules-3.0.1       \
-       gtk-update-icon-cache-3.0.1     \
-       gtk-builder-convert-3.0.1
+       gtk-update-icon-cache.1         \
+       gtk-builder-convert.1
 
 if ENABLE_MAN
 
diff --git a/docs/reference/gtk/gtk-builder-convert-3.0.xml b/docs/reference/gtk/gtk-builder-convert-3.0.xml
deleted file mode 100644 (file)
index eccfe33..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-<refentry id="gtk-builder-convert">
-
-<refmeta>
-<refentrytitle>gtk-builder-convert-3.0</refentrytitle>
-<manvolnum>1</manvolnum>
-</refmeta>
-
-<refnamediv>
-<refname>gtk-builder-convert-3.0</refname>
-<refpurpose>Glade file conversion utility</refpurpose>
-</refnamediv>
-
-<refsynopsisdiv>
-<cmdsynopsis>
-<command>gtk-builder-convert-3.0</command>
-<arg choice="opt">--skip-windows</arg>
-<arg choice="opt">--root <replaceable>name</replaceable></arg>
-<arg choice="req">input</arg>
-<arg choice="req">output</arg>
-</cmdsynopsis>
-</refsynopsisdiv>
-
-<refsect1><title>Description</title>
-<para><command>gtk-builder-convert-3.0</command> converts glade files
-into XML files which can be loaded with GtkBuilder.
-</para>
-<para>
-It expects the name of a glade file as the first argument, and writes
-its output the file specified as the second argument.
-</para>
-</refsect1>
-
-<refsect1><title>Options</title>
-<variablelist>
-  <varlistentry>
-    <term>--skip-windows</term>
-    <term>-w</term>
-    <listitem><para>Convert everything but GtkWindow subclasses.</para></listitem>
-  </varlistentry>
-  <varlistentry>
-    <term>--root</term>
-    <term>-r</term>
-    <listitem><para>Convert only the widget named <replaceable>name</replaceable> 
-       and its children.</para></listitem>
-  </varlistentry>
-</variablelist>
-</refsect1>
-
-<refsect1><title>Bugs</title>
-<para>
-Toolbars are not handled.
-</para>
-<para>
-Support for accessibility is not yet implemented.
-</para>
-<para>
-The script requires a python interpreter to run.
-</para>
-</refsect1>
-
-</refentry>
diff --git a/docs/reference/gtk/gtk-builder-convert.xml b/docs/reference/gtk/gtk-builder-convert.xml
new file mode 100644 (file)
index 0000000..aa98d5d
--- /dev/null
@@ -0,0 +1,61 @@
+<refentry id="gtk-builder-convert">
+
+<refmeta>
+<refentrytitle>gtk-builder-convert</refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+
+<refnamediv>
+<refname>gtk-builder-convert</refname>
+<refpurpose>Glade file conversion utility</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+<cmdsynopsis>
+<command>gtk-builder-convert</command>
+<arg choice="opt">--skip-windows</arg>
+<arg choice="opt">--root <replaceable>name</replaceable></arg>
+<arg choice="req">input</arg>
+<arg choice="req">output</arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para><command>gtk-builder-convert</command> converts glade files
+into XML files which can be loaded with GtkBuilder.
+</para>
+<para>
+It expects the name of a glade file as the first argument, and writes
+its output the file specified as the second argument.
+</para>
+</refsect1>
+
+<refsect1><title>Options</title>
+<variablelist>
+  <varlistentry>
+    <term>--skip-windows</term>
+    <term>-w</term>
+    <listitem><para>Convert everything but GtkWindow subclasses.</para></listitem>
+  </varlistentry>
+  <varlistentry>
+    <term>--root</term>
+    <term>-r</term>
+    <listitem><para>Convert only the widget named <replaceable>name</replaceable>
+       and its children.</para></listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>Bugs</title>
+<para>
+Toolbars are not handled.
+</para>
+<para>
+Support for accessibility is not yet implemented.
+</para>
+<para>
+The script requires a python interpreter to run.
+</para>
+</refsect1>
+
+</refentry>
index 39b9624c0a1595c43b43c5e40809da6444ecbc18..ca98b8f6fa4945f7a33817fb0d9c96d95cd2fdd9 100644 (file)
   <part>
     <title>GTK+ Tools</title>
     <xi:include href="gtk-query-immodules-3.0.xml" />
-    <xi:include href="gtk-update-icon-cache-3.0.xml" />
-    <xi:include href="gtk-builder-convert-3.0.xml" />
+    <xi:include href="gtk-update-icon-cache.xml" />
+    <xi:include href="gtk-builder-convert.xml" />
   </part>
 
   <xi:include href="glossary.xml" />
diff --git a/docs/reference/gtk/gtk-update-icon-cache-3.0.xml b/docs/reference/gtk/gtk-update-icon-cache-3.0.xml
deleted file mode 100644 (file)
index 477f37c..0000000
+++ /dev/null
@@ -1,108 +0,0 @@
-<?xml version="1.0"?>
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
-               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
-]>
-<refentry id="gtk-update-icon-cache">
-
-<refmeta>
-<refentrytitle>gtk-update-icon-cache-3.0</refentrytitle>
-<manvolnum>1</manvolnum>
-</refmeta>
-
-<refnamediv>
-<refname>gtk-update-icon-cache-3.0</refname>
-<refpurpose>Icon theme caching utility</refpurpose>
-</refnamediv>
-
-<refsynopsisdiv>
-<cmdsynopsis>
-<command>gtk-update-icon-cache-3.0</command>
-<arg choice="opt">--force</arg>
-<arg choice="opt">--ignore-theme-index</arg>
-<arg choice="opt">--index-only</arg>
-<arg choice="opt">--source<arg>name</arg></arg>
-<arg choice="opt">--quiet</arg>
-<arg choice="opt">--validate</arg>
-<arg choice="req">iconpath</arg>
-</cmdsynopsis>
-</refsynopsisdiv>
-
-<refsect1><title>Description</title>
-<para>
-  <command>gtk-update-icon-cache-3.0</command> creates mmap()able cache
-  files for icon themes.
-</para>
-<para>
-  It expects to be given the path to a icon theme directory containing an
-  <filename>index.theme</filename>, e.g. <filename>/usr/share/icons/hicolor</filename>,
-  and writes a <filename>icon-theme.cache</filename> containing cached
-  information about the icons in the directory tree below the given directory.
-</para>
-<para>
-  GTK+ can use the cache files created by <command>gtk-update-icon-cache-3.0</command>
-  to avoid a lot of system call and disk seek overhead when the application
-  starts. Since the format of the cache files allows them to be mmap()ed
-  shared between multiple applications, the overall memory consumption is
-  reduced as well.
-</para>
-</refsect1>
-
-<refsect1><title>Options</title>
-<variablelist>
-  <varlistentry>
-    <term>--force</term>
-    <term>-f</term>
-    <listitem><para>Overwrite an existing cache file even if it appears to be
-         uptodate.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term>--ignore-theme-index</term>
-    <term>-t</term>
-    <listitem><para>Don't check for the existence of 'index.theme' in the icon
-     theme directory. Without this option, <command>gtk-update-icon-cache-3.0</command>
-     refuses to create an icon cache in a directory which does not appear to
-     be the toplevel directory of an icon theme.
-    </para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term>--index-only</term>
-    <term>-i</term>
-    <listitem><para>Don't include image data in the cache.
-    </para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term>--source</term>
-    <term>-c</term>
-    <listitem><para>Output a C header file declaring a constant
-     <replaceable>name</replaceable> with the contents of the icon
-     cache.</para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term>--quiet</term>
-    <term>-q</term>
-    <listitem><para>Turn off verbose output.
-    </para></listitem>
-  </varlistentry>
-
-  <varlistentry>
-    <term>--validate</term>
-    <term>-v</term>
-    <listitem><para>Validate existing icon cache.
-    </para></listitem>
-  </varlistentry>
-</variablelist>
-</refsect1>
-
-<refsect1><title>Bugs</title>
-<para>
-None known yet.
-</para>
-</refsect1>
-
-</refentry>
-
-
diff --git a/docs/reference/gtk/gtk-update-icon-cache.xml b/docs/reference/gtk/gtk-update-icon-cache.xml
new file mode 100644 (file)
index 0000000..2a5bc27
--- /dev/null
@@ -0,0 +1,106 @@
+<?xml version="1.0"?>
+<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.3//EN"
+               "http://www.oasis-open.org/docbook/xml/4.3/docbookx.dtd" [
+]>
+<refentry id="gtk-update-icon-cache">
+
+<refmeta>
+<refentrytitle>gtk-update-icon-cache</refentrytitle>
+<manvolnum>1</manvolnum>
+</refmeta>
+
+<refnamediv>
+<refname>gtk-update-icon-cache</refname>
+<refpurpose>Icon theme caching utility</refpurpose>
+</refnamediv>
+
+<refsynopsisdiv>
+<cmdsynopsis>
+<command>gtk-update-icon-cache</command>
+<arg choice="opt">--force</arg>
+<arg choice="opt">--ignore-theme-index</arg>
+<arg choice="opt">--index-only</arg>
+<arg choice="opt">--source<arg>name</arg></arg>
+<arg choice="opt">--quiet</arg>
+<arg choice="opt">--validate</arg>
+<arg choice="req">iconpath</arg>
+</cmdsynopsis>
+</refsynopsisdiv>
+
+<refsect1><title>Description</title>
+<para>
+  <command>gtk-update-icon-cache</command> creates mmap()able cache
+  files for icon themes.
+</para>
+<para>
+  It expects to be given the path to a icon theme directory containing an
+  <filename>index.theme</filename>, e.g. <filename>/usr/share/icons/hicolor</filename>,
+  and writes a <filename>icon-theme.cache</filename> containing cached
+  information about the icons in the directory tree below the given directory.
+</para>
+<para>
+  GTK+ can use the cache files created by <command>gtk-update-icon-cache</command>
+  to avoid a lot of system call and disk seek overhead when the application
+  starts. Since the format of the cache files allows them to be mmap()ed
+  shared between multiple applications, the overall memory consumption is
+  reduced as well.
+</para>
+</refsect1>
+
+<refsect1><title>Options</title>
+<variablelist>
+  <varlistentry>
+    <term>--force</term>
+    <term>-f</term>
+    <listitem><para>Overwrite an existing cache file even if it appears to be
+         uptodate.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term>--ignore-theme-index</term>
+    <term>-t</term>
+    <listitem><para>Don't check for the existence of 'index.theme' in the icon
+     theme directory. Without this option, <command>gtk-update-icon-cache</command>
+     refuses to create an icon cache in a directory which does not appear to
+     be the toplevel directory of an icon theme.
+    </para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term>--index-only</term>
+    <term>-i</term>
+    <listitem><para>Don't include image data in the cache.
+    </para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term>--source</term>
+    <term>-c</term>
+    <listitem><para>Output a C header file declaring a constant
+     <replaceable>name</replaceable> with the contents of the icon
+     cache.</para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term>--quiet</term>
+    <term>-q</term>
+    <listitem><para>Turn off verbose output.
+    </para></listitem>
+  </varlistentry>
+
+  <varlistentry>
+    <term>--validate</term>
+    <term>-v</term>
+    <listitem><para>Validate existing icon cache.
+    </para></listitem>
+  </varlistentry>
+</variablelist>
+</refsect1>
+
+<refsect1><title>Bugs</title>
+<para>
+None known yet.
+</para>
+</refsect1>
+
+</refentry>
index d04e253256c449a4e1207df6cad3f45f0712177a..215f30577740a7e2a658a85f5d262bc9112fb9ff 100644 (file)
@@ -990,18 +990,18 @@ endif
 #
 bin_PROGRAMS = \
        gtk-query-immodules-3.0 \
-       gtk-update-icon-cache-3.0
+       gtk-update-icon-cache
 
-bin_SCRIPTS = gtk-builder-convert-3.0
+bin_SCRIPTS = gtk-builder-convert
 
 if OS_WIN32
 
 # Workaround for UAC silliness: programs with "update" in their name
 # are believed to be installers and require elevated privileges to be
 # used... Use a manifest file to tell Windows that
-# gtk-update-icon-cache-3.0.exe doesn't require any special privileges.
+# gtk-update-icon-cache.exe doesn't require any special privileges.
 
-GTK_UPDATE_ICON_CACHE_MANIFEST = gtk-update-icon-cache-3.0.exe.manifest
+GTK_UPDATE_ICON_CACHE_MANIFEST = gtk-update-icon-cache.exe.manifest
 
 bin_SCRIPTS += \
        $(GTK_UPDATE_ICON_CACHE_MANIFEST)
@@ -1011,7 +1011,7 @@ $(GTK_UPDATE_ICON_CACHE_MANIFEST):
         echo '<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">' ; \
         echo '  <assemblyIdentity version="1.0.0.0"' ; \
         echo '     processorArchitecture="'$(EXE_MANIFEST_ARCHITECTURE)'"' ; \
-        echo '     name="gtk-update-icon-cache-3.0.exe"' ; \
+        echo '     name="gtk-update-icon-cache.exe"' ; \
         echo '     type="win32"/>' ; \
         echo '  <!-- Identify the application security requirements. -->' ; \
         echo '  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">' ; \
@@ -1031,8 +1031,8 @@ gtk_query_immodules_3_0_DEPENDENCIES = $(DEPS)
 gtk_query_immodules_3_0_LDADD = $(LDADDS)
 gtk_query_immodules_3_0_SOURCES = queryimmodules.c
 
-gtk_update_icon_cache_3_0_LDADD = $(GDK_PIXBUF_LIBS)
-gtk_update_icon_cache_3_0_SOURCES = updateiconcache.c
+gtk_update_icon_cache_LDADD = $(GDK_PIXBUF_LIBS)
+gtk_update_icon_cache_SOURCES = updateiconcache.c
 
 .PHONY: files test test-debug
 
@@ -1329,12 +1329,12 @@ if CROSS_COMPILING
 gtk_update_icon_cache_program = $(GTK_UPDATE_ICON_CACHE)
 else
 gtk_update_icon_cache_program =                                                        \
-          ./gtk-update-icon-cache-3.0
+          ./gtk-update-icon-cache
 endif
 
 gtkbuiltincache.h: @REBUILD@ stamp-icons
-       $(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache-3.0$(EXEEXT) $(GTK_UPDATE_ICON_CACHE_MANIFEST)
-       $(gtk_update_icon_cache_program) --force --ignore-theme-index           \
+       $(AM_V_at) $(MAKE) $(AM_MAKEFLAGS) gtk-update-icon-cache$(EXEEXT) $(GTK_UPDATE_ICON_CACHE_MANIFEST)
+       $(AM_V_GEN) $(gtk_update_icon_cache_program) --quiet --force --ignore-theme-index               \
           --source builtin_icons stock-icons > gtkbuiltincache.h.tmp &&        \
        mv gtkbuiltincache.h.tmp gtkbuiltincache.h
 
@@ -1348,7 +1348,7 @@ EXTRA_DIST +=                   \
        tree_minus.xpm          \
        tree_plus.xpm           \
        gtk.def                 \
-       gtk-builder-convert-3.0 \
+       gtk-builder-convert     \
        gtk-win32.rc            \
        gtk-win32.rc.in         \
        gtkwin32embed.h         \
diff --git a/gtk/gtk-builder-convert b/gtk/gtk-builder-convert
new file mode 100755 (executable)
index 0000000..4cae240
--- /dev/null
@@ -0,0 +1,772 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2006-2008 Async Open Source
+#                         Henrique Romano <henrique@async.com.br>
+#                         Johan Dahlin <jdahlin@async.com.br>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# TODO:
+#  Toolbars
+
+"""Usage: gtk-builder-convert-3.0 [OPTION] [INPUT] [OUTPUT]
+Converts Glade files into XML files which can be loaded with GtkBuilder.
+The [INPUT] file is
+
+  -w, --skip-windows     Convert everything but GtkWindow subclasses.
+  -r, --root             Convert only widget named root and its children
+  -h, --help             display this help and exit
+
+When OUTPUT is -, write to standard output.
+
+Examples:
+  gtk-builder-convert-3.0 preference.glade preferences.ui
+
+Report bugs to http://bugzilla.gnome.org/."""
+
+import getopt
+import os
+import sys
+
+from xml.dom import minidom, Node
+
+DIALOGS = ['GtkDialog',
+           'GtkFileChooserDialog',
+           'GtkMessageDialog']
+WINDOWS = ['GtkWindow'] + DIALOGS
+
+# The subprocess is only available in Python 2.4+
+try:
+    import subprocess
+    subprocess # pyflakes
+except ImportError:
+    subprocess = None
+
+def get_child_nodes(node):
+    assert node.tagName == 'object'
+    nodes = []
+    for child in node.childNodes:
+        if child.nodeType != Node.ELEMENT_NODE:
+            continue
+        if child.tagName != 'child':
+            continue
+        nodes.append(child)
+    return nodes
+
+def get_properties(node):
+    assert node.tagName == 'object'
+    properties = {}
+    for child in node.childNodes:
+        if child.nodeType != Node.ELEMENT_NODE:
+            continue
+        if child.tagName != 'property':
+            continue
+        value = child.childNodes[0].data
+        properties[child.getAttribute('name')] = value
+    return properties
+
+def get_property(node, property_name):
+    assert node.tagName == 'object'
+    properties = get_properties(node)
+    return properties.get(property_name)
+
+def get_property_node(node, property_name):
+    assert node.tagName == 'object'
+    properties = {}
+    for child in node.childNodes:
+        if child.nodeType != Node.ELEMENT_NODE:
+            continue
+        if child.tagName != 'property':
+            continue
+        if child.getAttribute('name') == property_name:
+            return child
+
+def get_signal_nodes(node):
+    assert node.tagName == 'object'
+    signals = []
+    for child in node.childNodes:
+        if child.nodeType != Node.ELEMENT_NODE:
+            continue
+        if child.tagName == 'signal':
+            signals.append(child)
+    return signals
+
+def get_property_nodes(node):
+    assert node.tagName == 'object'
+    properties = []
+    for child in node.childNodes:
+        if child.nodeType != Node.ELEMENT_NODE:
+            continue
+        # FIXME: handle comments
+        if child.tagName == 'property':
+            properties.append(child)
+    return properties
+
+def get_accelerator_nodes(node):
+    assert node.tagName == 'object'
+    accelerators = []
+    for child in node.childNodes:
+        if child.nodeType != Node.ELEMENT_NODE:
+            continue
+        if child.tagName == 'accelerator':
+            accelerators.append(child)
+    return accelerators
+
+def get_object_node(child_node):
+    assert child_node.tagName == 'child', child_node
+    nodes = []
+    for node in child_node.childNodes:
+        if node.nodeType != Node.ELEMENT_NODE:
+            continue
+        if node.tagName == 'object':
+            nodes.append(node)
+    assert len(nodes) == 1, nodes
+    return nodes[0]
+
+def copy_properties(node, props, prop_dict):
+    assert node.tagName == 'object'
+    for prop_name in props:
+        child = get_property_node(node, prop_name)
+        if child is not None:
+            prop_dict[prop_name] = child
+
+    return node
+
+class GtkBuilderConverter(object):
+
+    def __init__(self, skip_windows, root):
+        self.skip_windows = skip_windows
+        self.root = root
+        self.root_objects = []
+        self.objects = {}
+
+    #
+    # Public API
+    #
+
+    def parse_file(self, file):
+        self._dom = minidom.parse(file)
+        self._parse()
+
+    def parse_buffer(self, buffer):
+        self._dom = minidom.parseString(buffer)
+        self._parse()
+
+    def to_xml(self):
+        xml = self._dom.toprettyxml("", "")
+        return xml.encode('utf-8')
+
+    #
+    # Private
+    #
+
+    def _get_object(self, name):
+        return self.objects.get(name)
+
+    def _get_objects_by_attr(self, attribute, value):
+        return [w for w in self._dom.getElementsByTagName("object")
+                      if w.getAttribute(attribute) == value]
+
+    def _create_object(self, obj_class, obj_id, template=None, properties=None):
+        """
+        Creates a new <object> tag.
+        Optionally a name template can be provided which will be used
+        to avoid naming collisions.
+        The properties dictionary can either contain string values or Node
+        values. If a node is provided the name of the node will be overridden
+        by the dictionary key.
+
+        @param obj_class: class of the object (class tag)
+        @param obj_id: identifier of the object (id tag)
+        @param template: name template to use, for example 'button'
+        @param properties: dictionary of properties
+        @type properties: string or Node.
+        @returns: Newly created node of the object
+        """
+        if template is not None:
+            count = 1
+            while True:
+                obj_id = template + str(count)
+                widget = self._get_object(obj_id)
+                if widget is None:
+                    break
+
+                count += 1
+
+        obj = self._dom.createElement('object')
+        obj.setAttribute('class', obj_class)
+        obj.setAttribute('id', obj_id)
+        if properties:
+            for name, value in properties.items():
+                if isinstance(value, Node):
+                    # Reuse the node, so translatable and context still will be
+                    # set when converting nodes. See also #509153
+                    prop = value
+                else:
+                    prop = self._dom.createElement('property')
+                    prop.appendChild(self._dom.createTextNode(value))
+
+                prop.setAttribute('name', str(name))
+                obj.appendChild(prop)
+        self.objects[obj_id] = obj
+        return obj
+
+    def _create_root_object(self, obj_class, template, properties=None):
+        obj = self._create_object(obj_class, None, template, properties)
+        self.root_objects.append(obj)
+        return obj
+
+    def _parse(self):
+        glade_iface = self._dom.getElementsByTagName("glade-interface")
+        assert glade_iface, ("Badly formed XML, there is "
+                             "no <glade-interface> tag.")
+        # Rename glade-interface to interface
+        glade_iface[0].tagName = 'interface'
+        self._interface = glade_iface[0]
+
+        # Remove glade-interface doc type
+        for node in self._dom.childNodes:
+            if node.nodeType == Node.DOCUMENT_TYPE_NODE:
+                if node.name == 'glade-interface':
+                    self._dom.removeChild(node)
+
+        # Strip unsupported tags
+        for tag in ['requires', 'requires-version']:
+            for child in self._dom.getElementsByTagName(tag):
+                child.parentNode.removeChild(child)
+
+        if self.root:
+            self._strip_root(self.root)
+
+        # Rename widget to object
+        objects = self._dom.getElementsByTagName("widget")
+        for node in objects:
+            node.tagName = "object"
+
+        for node in objects:
+            self._convert(node.getAttribute("class"), node)
+            if self._get_object(node.getAttribute('id')) is not None:
+                print "WARNING: duplicate id \"" + node.getAttribute('id') + "\""
+            self.objects[node.getAttribute('id')] = node
+
+        # Convert Gazpachos UI tag
+        for node in self._dom.getElementsByTagName("ui"):
+            self._convert_ui(node)
+
+        # Convert accessibility tag
+        for node in self._dom.getElementsByTagName("accessibility"):
+            self._convert_accessibility(node)
+
+        # Output the newly created root objects and sort them
+        # by attribute id
+        # FIXME: Use sorted(self.root_objects,
+        #                   key=lambda n: n.getAttribute('id'),
+        #                   reverse=True):
+        # when we can depend on python 2.4 or higher
+        root_objects = self.root_objects[:]
+        root_objects.sort(lambda a, b: cmp(b.getAttribute('id'),
+                                           a.getAttribute('id')))
+        for obj in root_objects:
+            self._interface.childNodes.insert(0, obj)
+
+    def _convert(self, klass, node):
+        if klass == 'GtkNotebook':
+            self._packing_prop_to_child_attr(node, "type", "tab")
+        elif klass in ['GtkExpander', 'GtkFrame']:
+            self._packing_prop_to_child_attr(
+                node, "type", "label_item", "label")
+        elif klass == "GtkMenuBar":
+            self._convert_menu(node)
+        elif klass == "GtkMenu":
+            # Only convert toplevel popups
+            if node.parentNode == self._interface:
+                self._convert_menu(node, popup=True)
+        elif klass in WINDOWS and self.skip_windows:
+            self._remove_window(node)
+        self._default_widget_converter(node)
+
+    def _default_widget_converter(self, node):
+        klass = node.getAttribute("class")
+        for prop in get_property_nodes(node):
+            prop_name = prop.getAttribute("name")
+            if prop_name == "sizegroup":
+                self._convert_sizegroup(node, prop)
+            elif prop_name == "tooltip" and klass != "GtkAction":
+                prop.setAttribute("name", "tooltip-text")
+            elif prop_name in ["response_id", 'response-id']:
+                # It does not make sense to convert responses when
+                # we're not going to output dialogs
+                if self.skip_windows:
+                    continue
+                object_id = node.getAttribute('id')
+                response = prop.childNodes[0].data
+                self._convert_dialog_response(node, object_id, response)
+                prop.parentNode.removeChild(prop)
+            elif prop_name == "adjustment":
+                self._convert_adjustment(prop)
+            elif prop_name == "items" and klass in ['GtkComboBox',
+                                                    'GtkComboBoxEntry']:
+                self._convert_combobox_items(node, prop)
+            elif prop_name == "text" and klass == 'GtkTextView':
+                self._convert_textview_text(prop)
+
+    def _remove_window(self, node):
+        object_node = get_object_node(get_child_nodes(node)[0])
+        parent = node.parentNode
+        parent.removeChild(node)
+        parent.appendChild(object_node)
+
+    def _convert_menu(self, node, popup=False):
+        if node.hasAttribute('constructor'):
+            return
+
+        uimgr = self._create_root_object('GtkUIManager',
+                                         template='uimanager')
+
+        if popup:
+            name = 'popup'
+        else:
+            name = 'menubar'
+
+        menu = self._dom.createElement(name)
+        menu.setAttribute('name', node.getAttribute('id'))
+        node.setAttribute('constructor', uimgr.getAttribute('id'))
+
+        for child in get_child_nodes(node):
+            obj_node = get_object_node(child)
+            item = self._convert_menuitem(uimgr, obj_node)
+            menu.appendChild(item)
+            child.removeChild(obj_node)
+            child.parentNode.removeChild(child)
+
+        ui = self._dom.createElement('ui')
+        uimgr.appendChild(ui)
+
+        ui.appendChild(menu)
+
+    def _convert_menuitem(self, uimgr, obj_node):
+        children = get_child_nodes(obj_node)
+        name = 'menuitem'
+        if children:
+            child_node = children[0]
+            menu_node = get_object_node(child_node)
+            # Can be GtkImage, which will take care of later.
+            if menu_node.getAttribute('class') == 'GtkMenu':
+                name = 'menu'
+
+        object_class = obj_node.getAttribute('class')
+        if object_class in ['GtkMenuItem',
+                            'GtkImageMenuItem',
+                            'GtkCheckMenuItem',
+                            'GtkRadioMenuItem']:
+            menu = self._dom.createElement(name)
+        elif object_class == 'GtkSeparatorMenuItem':
+            return self._dom.createElement('separator')
+        else:
+            raise NotImplementedError(object_class)
+
+        menu.setAttribute('action', obj_node.getAttribute('id'))
+        self._add_action_from_menuitem(uimgr, obj_node)
+        if children:
+            for child in get_child_nodes(menu_node):
+                obj_node = get_object_node(child)
+                item = self._convert_menuitem(uimgr, obj_node)
+                menu.appendChild(item)
+                child.removeChild(obj_node)
+                child.parentNode.removeChild(child)
+        return menu
+
+    def _menuitem_to_action(self, node, properties):
+        copy_properties(node, ['label', 'tooltip'], properties)
+
+    def _togglemenuitem_to_action(self, node, properties):
+        self._menuitem_to_action(node, properties)
+        copy_properties(node, ['active'], properties)
+
+    def _radiomenuitem_to_action(self, node, properties):
+        self._togglemenuitem_to_action(node, properties)
+        copy_properties(node, ['group'], properties)
+
+    def _add_action_from_menuitem(self, uimgr, node):
+        properties = {}
+        object_class = node.getAttribute('class')
+        object_id = node.getAttribute('id')
+        if object_class == 'GtkMenuItem':
+            name = 'GtkAction'
+            self._menuitem_to_action(node, properties)
+        elif object_class == 'GtkCheckMenuItem':
+            name = 'GtkToggleAction'
+            self._togglemenuitem_to_action(node, properties)
+        elif object_class == 'GtkRadioMenuItem':
+            name = 'GtkRadioAction'
+            self._radiomenuitem_to_action(node, properties)
+        elif object_class == 'GtkImageMenuItem':
+            name = 'GtkAction'
+            children = get_child_nodes(node)
+            if (children and
+                children[0].getAttribute('internal-child') == 'image'):
+                image = get_object_node(children[0])
+                child = get_property_node(image, 'stock')
+                if child is not None:
+                    properties['stock_id'] = child
+            self._menuitem_to_action(node, properties)
+        elif object_class == 'GtkSeparatorMenuItem':
+            return
+        else:
+            raise NotImplementedError(object_class)
+
+        if get_property(node, 'use_stock') == 'True':
+            if 'label' in properties:
+                properties['stock_id'] = properties['label']
+                del properties['label']
+
+        properties['name'] = object_id
+        action = self._create_object(name,
+                                     object_id,
+                                     properties=properties)
+        for signal in get_signal_nodes(node):
+            signal_name = signal.getAttribute('name')
+            if signal_name in ['activate', 'toggled']:
+                action.appendChild(signal)
+            else:
+                print 'Unhandled signal %s::%s' % (node.getAttribute('class'),
+                                                   signal_name)
+
+        if not uimgr.childNodes:
+            child = self._dom.createElement('child')
+            uimgr.appendChild(child)
+
+            group = self._create_object('GtkActionGroup', None,
+                                        template='actiongroup')
+            child.appendChild(group)
+        else:
+            group = uimgr.childNodes[0].childNodes[0]
+
+        child = self._dom.createElement('child')
+        group.appendChild(child)
+        child.appendChild(action)
+
+        for accelerator in get_accelerator_nodes(node):
+            signal_name = accelerator.getAttribute('signal')
+            if signal_name != 'activate':
+                print 'Unhandled accelerator signal for %s::%s' % (
+                    node.getAttribute('class'), signal_name)
+                continue
+            accelerator.removeAttribute('signal')
+            child.appendChild(accelerator)
+
+    def _convert_sizegroup(self, node, prop):
+        # This is Gazpacho only
+        node.removeChild(prop)
+        obj = self._get_object(prop.childNodes[0].data)
+        if obj is None:
+            widgets = self._get_objects_by_attr("class", "GtkSizeGroup")
+            if widgets:
+                obj = widgets[-1]
+            else:
+                obj = self._create_root_object('GtkSizeGroup',
+                                               template='sizegroup')
+
+        widgets = obj.getElementsByTagName("widgets")
+        if widgets:
+            assert len(widgets) == 1
+            widgets = widgets[0]
+        else:
+            widgets = self._dom.createElement("widgets")
+            obj.appendChild(widgets)
+
+        member = self._dom.createElement("widget")
+        member.setAttribute("name", node.getAttribute("id"))
+        widgets.appendChild(member)
+
+    def _convert_dialog_response(self, node, object_name, response):
+        # 1) Get parent dialog node
+        while True:
+            # If we can't find the parent dialog, give up
+            if node == self._dom:
+                return
+
+            if (node.tagName == 'object' and
+                node.getAttribute('class') in DIALOGS):
+                dialog = node
+                break
+            node = node.parentNode
+            assert node
+
+        # 2) Get dialogs action-widgets tag, create if not found
+        for child in dialog.childNodes:
+            if child.nodeType != Node.ELEMENT_NODE:
+                continue
+            if child.tagName == 'action-widgets':
+                actions = child
+                break
+        else:
+            actions = self._dom.createElement("action-widgets")
+            dialog.appendChild(actions)
+
+        # 3) Add action-widget tag for the response
+        action = self._dom.createElement("action-widget")
+        action.setAttribute("response", response)
+        action.appendChild(self._dom.createTextNode(object_name))
+        actions.appendChild(action)
+
+    def _convert_adjustment(self, prop):
+        properties = {}
+        if prop.childNodes:
+            data = prop.childNodes[0].data
+            value, lower, upper, step, page, page_size = data.split(' ')
+            properties.update(value=value,
+                              lower=lower,
+                              upper=upper,
+                              step_increment=step,
+                              page_increment=page,
+                              page_size=page_size)
+        else:
+            prop.appendChild(self._dom.createTextNode(""))
+
+        adj = self._create_root_object("GtkAdjustment",
+                                       template='adjustment',
+                                       properties=properties)
+        prop.childNodes[0].data = adj.getAttribute('id')
+
+    def _convert_combobox_items(self, node, prop):
+        parent = prop.parentNode
+        if not prop.childNodes:
+            parent.removeChild(prop)
+            return
+
+        translatable_attr = prop.attributes.get('translatable')
+        translatable = translatable_attr is not None and translatable_attr.value == 'yes'
+        has_context_attr = prop.attributes.get('context')
+        has_context = has_context_attr is not None and has_context_attr.value == 'yes'
+        comments_attr = prop.attributes.get('comments')
+        comments = comments_attr is not None and comments_attr.value or None
+
+        value = prop.childNodes[0].data
+        model = self._create_root_object("GtkListStore",
+                                         template="model")
+
+        columns = self._dom.createElement('columns')
+        model.appendChild(columns)
+
+        column = self._dom.createElement('column')
+        column.setAttribute('type', 'gchararray')
+        columns.appendChild(column)
+
+        data = self._dom.createElement('data')
+        model.appendChild(data)
+
+        if value.endswith('\n'):
+            value = value[:-1]
+        for item in value.split('\n'):
+            row = self._dom.createElement('row')
+            data.appendChild(row)
+
+            col = self._dom.createElement('col')
+            col.setAttribute('id', '0')
+            if translatable:
+                col.setAttribute('translatable', 'yes')
+            if has_context:
+                splitting = item.split('|', 1)
+                if len(splitting) == 2:
+                    context, item = splitting
+                    col.setAttribute('context', context)
+            if comments is not None:
+                col.setAttribute('comments', comments)
+            col.appendChild(self._dom.createTextNode(item))
+            row.appendChild(col)
+
+        model_prop = self._dom.createElement('property')
+        model_prop.setAttribute('name', 'model')
+        model_prop.appendChild(
+            self._dom.createTextNode(model.getAttribute('id')))
+        parent.appendChild(model_prop)
+
+        parent.removeChild(prop)
+
+        child = self._dom.createElement('child')
+        node.appendChild(child)
+        cell_renderer = self._create_object('GtkCellRendererText', None,
+                                            template='renderer')
+        child.appendChild(cell_renderer)
+
+        attributes = self._dom.createElement('attributes')
+        child.appendChild(attributes)
+
+        attribute = self._dom.createElement('attribute')
+        attributes.appendChild(attribute)
+        attribute.setAttribute('name', 'text')
+        attribute.appendChild(self._dom.createTextNode('0'))
+
+    def _convert_textview_text(self, prop):
+        if not prop.childNodes:
+            prop.parentNode.removeChild(prop)
+            return
+
+        data = prop.childNodes[0].data
+        if prop.hasAttribute('translatable'):
+            prop.removeAttribute('translatable')
+        tbuffer = self._create_root_object("GtkTextBuffer",
+                                           template='textbuffer',
+                                           properties=dict(text=data))
+        prop.childNodes[0].data = tbuffer.getAttribute('id')
+        prop.setAttribute('name', 'buffer')
+
+    def _packing_prop_to_child_attr(self, node, prop_name, prop_val,
+                                   attr_val=None):
+        for child in get_child_nodes(node):
+            packing_props = [p for p in child.childNodes if p.nodeName == "packing"]
+            if not packing_props:
+                continue
+            assert len(packing_props) == 1
+            packing_prop = packing_props[0]
+            properties = packing_prop.getElementsByTagName("property")
+            for prop in properties:
+                if (prop.getAttribute("name") != prop_name or
+                    prop.childNodes[0].data != prop_val):
+                    continue
+                packing_prop.removeChild(prop)
+                child.setAttribute(prop_name, attr_val or prop_val)
+            if len(properties) == 1:
+                child.removeChild(packing_prop)
+
+    def _convert_ui(self, node):
+        cdata = node.childNodes[0]
+        data = cdata.toxml().strip()
+        if not data.startswith("<![CDATA[") or not data.endswith("]]>"):
+            return
+        data = data[9:-3]
+        child = minidom.parseString(data).childNodes[0]
+        nodes = child.childNodes[:]
+        for child_node in nodes:
+            node.appendChild(child_node)
+        node.removeChild(cdata)
+        if not node.hasAttribute("id"):
+            return
+
+        # Updating references made by widgets
+        parent_id = node.parentNode.getAttribute("id")
+        for widget in self._get_objects_by_attr("constructor",
+                                                node.getAttribute("id")):
+            widget.getAttributeNode("constructor").value = parent_id
+        node.removeAttribute("id")
+
+    def _convert_accessibility(self, node):
+        objectNode = node.parentNode
+        parent_id = objectNode.getAttribute("id")
+
+        properties = {}
+        for node in node.childNodes:
+            if node.nodeName == 'atkproperty':
+                node.tagName = 'property'
+                properties[node.getAttribute('name')] = node
+                node.parentNode.removeChild(node)
+            elif node.nodeName == 'atkrelation':
+                node.tagName = 'relation'
+                relation_type = node.getAttribute('type')
+                relation_type = relation_type.replace('_', '-')
+                node.setAttribute('type', relation_type)
+            elif node.nodeName == 'atkaction':
+                node.tagName = 'action'
+
+        if properties:
+            child = self._dom.createElement('child')
+            child.setAttribute("internal-child", "accessible")
+
+            atkobject = self._create_object(
+                "AtkObject", None,
+                template='a11y-%s' % (parent_id,),
+                properties=properties)
+            child.appendChild(atkobject)
+            objectNode.appendChild(child)
+
+    def _strip_root(self, root_name):
+        for widget in self._dom.getElementsByTagName("widget"):
+            if widget.getAttribute('id') == root_name:
+                break
+        else:
+            raise SystemExit("Could not find an object called `%s'" % (
+                root_name))
+
+        for child in self._interface.childNodes[:]:
+            if child.nodeType != Node.ELEMENT_NODE:
+                continue
+            child.parentNode.removeChild(child)
+
+        self._interface.appendChild(widget)
+
+
+def _indent(output):
+    if not subprocess:
+        return output
+
+    for directory in os.environ['PATH'].split(os.pathsep):
+        filename = os.path.join(directory, 'xmllint')
+        if os.path.exists(filename):
+            break
+    else:
+        return output
+
+    s = subprocess.Popen([filename, '--format', '-'],
+                         stdin=subprocess.PIPE,
+                         stdout=subprocess.PIPE)
+    s.stdin.write(output)
+    s.stdin.close()
+    return s.stdout.read()
+
+def usage():
+    print __doc__
+
+def main(args):
+    try:
+        opts, args = getopt.getopt(args[1:], "hwr:",
+                                   ["help", "skip-windows", "root="])
+    except getopt.GetoptError:
+        usage()
+        return 2
+
+    if len(args) != 2:
+        usage()
+        return 2
+
+    input_filename, output_filename = args
+
+    skip_windows = False
+    split = False
+    root = None
+    for o, a in opts:
+        if o in ("-h", "--help"):
+            usage()
+            sys.exit()
+        elif o in ("-r", "--root"):
+            root = a
+        elif o in ("-w", "--skip-windows"):
+            skip_windows = True
+
+    conv = GtkBuilderConverter(skip_windows=skip_windows,
+                               root=root)
+    conv.parse_file(input_filename)
+
+    xml = _indent(conv.to_xml())
+    if output_filename == "-":
+        print xml
+    else:
+        open(output_filename, 'w').write(xml)
+        print "Wrote", output_filename
+
+    return 0
+
+if __name__ == "__main__":
+    sys.exit(main(sys.argv))
diff --git a/gtk/gtk-builder-convert-3.0 b/gtk/gtk-builder-convert-3.0
deleted file mode 100755 (executable)
index 4cae240..0000000
+++ /dev/null
@@ -1,772 +0,0 @@
-#!/usr/bin/env python
-#
-# Copyright (C) 2006-2008 Async Open Source
-#                         Henrique Romano <henrique@async.com.br>
-#                         Johan Dahlin <jdahlin@async.com.br>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public License
-# as published by the Free Software Foundation; either version 2
-# of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-#
-# TODO:
-#  Toolbars
-
-"""Usage: gtk-builder-convert-3.0 [OPTION] [INPUT] [OUTPUT]
-Converts Glade files into XML files which can be loaded with GtkBuilder.
-The [INPUT] file is
-
-  -w, --skip-windows     Convert everything but GtkWindow subclasses.
-  -r, --root             Convert only widget named root and its children
-  -h, --help             display this help and exit
-
-When OUTPUT is -, write to standard output.
-
-Examples:
-  gtk-builder-convert-3.0 preference.glade preferences.ui
-
-Report bugs to http://bugzilla.gnome.org/."""
-
-import getopt
-import os
-import sys
-
-from xml.dom import minidom, Node
-
-DIALOGS = ['GtkDialog',
-           'GtkFileChooserDialog',
-           'GtkMessageDialog']
-WINDOWS = ['GtkWindow'] + DIALOGS
-
-# The subprocess is only available in Python 2.4+
-try:
-    import subprocess
-    subprocess # pyflakes
-except ImportError:
-    subprocess = None
-
-def get_child_nodes(node):
-    assert node.tagName == 'object'
-    nodes = []
-    for child in node.childNodes:
-        if child.nodeType != Node.ELEMENT_NODE:
-            continue
-        if child.tagName != 'child':
-            continue
-        nodes.append(child)
-    return nodes
-
-def get_properties(node):
-    assert node.tagName == 'object'
-    properties = {}
-    for child in node.childNodes:
-        if child.nodeType != Node.ELEMENT_NODE:
-            continue
-        if child.tagName != 'property':
-            continue
-        value = child.childNodes[0].data
-        properties[child.getAttribute('name')] = value
-    return properties
-
-def get_property(node, property_name):
-    assert node.tagName == 'object'
-    properties = get_properties(node)
-    return properties.get(property_name)
-
-def get_property_node(node, property_name):
-    assert node.tagName == 'object'
-    properties = {}
-    for child in node.childNodes:
-        if child.nodeType != Node.ELEMENT_NODE:
-            continue
-        if child.tagName != 'property':
-            continue
-        if child.getAttribute('name') == property_name:
-            return child
-
-def get_signal_nodes(node):
-    assert node.tagName == 'object'
-    signals = []
-    for child in node.childNodes:
-        if child.nodeType != Node.ELEMENT_NODE:
-            continue
-        if child.tagName == 'signal':
-            signals.append(child)
-    return signals
-
-def get_property_nodes(node):
-    assert node.tagName == 'object'
-    properties = []
-    for child in node.childNodes:
-        if child.nodeType != Node.ELEMENT_NODE:
-            continue
-        # FIXME: handle comments
-        if child.tagName == 'property':
-            properties.append(child)
-    return properties
-
-def get_accelerator_nodes(node):
-    assert node.tagName == 'object'
-    accelerators = []
-    for child in node.childNodes:
-        if child.nodeType != Node.ELEMENT_NODE:
-            continue
-        if child.tagName == 'accelerator':
-            accelerators.append(child)
-    return accelerators
-
-def get_object_node(child_node):
-    assert child_node.tagName == 'child', child_node
-    nodes = []
-    for node in child_node.childNodes:
-        if node.nodeType != Node.ELEMENT_NODE:
-            continue
-        if node.tagName == 'object':
-            nodes.append(node)
-    assert len(nodes) == 1, nodes
-    return nodes[0]
-
-def copy_properties(node, props, prop_dict):
-    assert node.tagName == 'object'
-    for prop_name in props:
-        child = get_property_node(node, prop_name)
-        if child is not None:
-            prop_dict[prop_name] = child
-
-    return node
-
-class GtkBuilderConverter(object):
-
-    def __init__(self, skip_windows, root):
-        self.skip_windows = skip_windows
-        self.root = root
-        self.root_objects = []
-        self.objects = {}
-
-    #
-    # Public API
-    #
-
-    def parse_file(self, file):
-        self._dom = minidom.parse(file)
-        self._parse()
-
-    def parse_buffer(self, buffer):
-        self._dom = minidom.parseString(buffer)
-        self._parse()
-
-    def to_xml(self):
-        xml = self._dom.toprettyxml("", "")
-        return xml.encode('utf-8')
-
-    #
-    # Private
-    #
-
-    def _get_object(self, name):
-        return self.objects.get(name)
-
-    def _get_objects_by_attr(self, attribute, value):
-        return [w for w in self._dom.getElementsByTagName("object")
-                      if w.getAttribute(attribute) == value]
-
-    def _create_object(self, obj_class, obj_id, template=None, properties=None):
-        """
-        Creates a new <object> tag.
-        Optionally a name template can be provided which will be used
-        to avoid naming collisions.
-        The properties dictionary can either contain string values or Node
-        values. If a node is provided the name of the node will be overridden
-        by the dictionary key.
-
-        @param obj_class: class of the object (class tag)
-        @param obj_id: identifier of the object (id tag)
-        @param template: name template to use, for example 'button'
-        @param properties: dictionary of properties
-        @type properties: string or Node.
-        @returns: Newly created node of the object
-        """
-        if template is not None:
-            count = 1
-            while True:
-                obj_id = template + str(count)
-                widget = self._get_object(obj_id)
-                if widget is None:
-                    break
-
-                count += 1
-
-        obj = self._dom.createElement('object')
-        obj.setAttribute('class', obj_class)
-        obj.setAttribute('id', obj_id)
-        if properties:
-            for name, value in properties.items():
-                if isinstance(value, Node):
-                    # Reuse the node, so translatable and context still will be
-                    # set when converting nodes. See also #509153
-                    prop = value
-                else:
-                    prop = self._dom.createElement('property')
-                    prop.appendChild(self._dom.createTextNode(value))
-
-                prop.setAttribute('name', str(name))
-                obj.appendChild(prop)
-        self.objects[obj_id] = obj
-        return obj
-
-    def _create_root_object(self, obj_class, template, properties=None):
-        obj = self._create_object(obj_class, None, template, properties)
-        self.root_objects.append(obj)
-        return obj
-
-    def _parse(self):
-        glade_iface = self._dom.getElementsByTagName("glade-interface")
-        assert glade_iface, ("Badly formed XML, there is "
-                             "no <glade-interface> tag.")
-        # Rename glade-interface to interface
-        glade_iface[0].tagName = 'interface'
-        self._interface = glade_iface[0]
-
-        # Remove glade-interface doc type
-        for node in self._dom.childNodes:
-            if node.nodeType == Node.DOCUMENT_TYPE_NODE:
-                if node.name == 'glade-interface':
-                    self._dom.removeChild(node)
-
-        # Strip unsupported tags
-        for tag in ['requires', 'requires-version']:
-            for child in self._dom.getElementsByTagName(tag):
-                child.parentNode.removeChild(child)
-
-        if self.root:
-            self._strip_root(self.root)
-
-        # Rename widget to object
-        objects = self._dom.getElementsByTagName("widget")
-        for node in objects:
-            node.tagName = "object"
-
-        for node in objects:
-            self._convert(node.getAttribute("class"), node)
-            if self._get_object(node.getAttribute('id')) is not None:
-                print "WARNING: duplicate id \"" + node.getAttribute('id') + "\""
-            self.objects[node.getAttribute('id')] = node
-
-        # Convert Gazpachos UI tag
-        for node in self._dom.getElementsByTagName("ui"):
-            self._convert_ui(node)
-
-        # Convert accessibility tag
-        for node in self._dom.getElementsByTagName("accessibility"):
-            self._convert_accessibility(node)
-
-        # Output the newly created root objects and sort them
-        # by attribute id
-        # FIXME: Use sorted(self.root_objects,
-        #                   key=lambda n: n.getAttribute('id'),
-        #                   reverse=True):
-        # when we can depend on python 2.4 or higher
-        root_objects = self.root_objects[:]
-        root_objects.sort(lambda a, b: cmp(b.getAttribute('id'),
-                                           a.getAttribute('id')))
-        for obj in root_objects:
-            self._interface.childNodes.insert(0, obj)
-
-    def _convert(self, klass, node):
-        if klass == 'GtkNotebook':
-            self._packing_prop_to_child_attr(node, "type", "tab")
-        elif klass in ['GtkExpander', 'GtkFrame']:
-            self._packing_prop_to_child_attr(
-                node, "type", "label_item", "label")
-        elif klass == "GtkMenuBar":
-            self._convert_menu(node)
-        elif klass == "GtkMenu":
-            # Only convert toplevel popups
-            if node.parentNode == self._interface:
-                self._convert_menu(node, popup=True)
-        elif klass in WINDOWS and self.skip_windows:
-            self._remove_window(node)
-        self._default_widget_converter(node)
-
-    def _default_widget_converter(self, node):
-        klass = node.getAttribute("class")
-        for prop in get_property_nodes(node):
-            prop_name = prop.getAttribute("name")
-            if prop_name == "sizegroup":
-                self._convert_sizegroup(node, prop)
-            elif prop_name == "tooltip" and klass != "GtkAction":
-                prop.setAttribute("name", "tooltip-text")
-            elif prop_name in ["response_id", 'response-id']:
-                # It does not make sense to convert responses when
-                # we're not going to output dialogs
-                if self.skip_windows:
-                    continue
-                object_id = node.getAttribute('id')
-                response = prop.childNodes[0].data
-                self._convert_dialog_response(node, object_id, response)
-                prop.parentNode.removeChild(prop)
-            elif prop_name == "adjustment":
-                self._convert_adjustment(prop)
-            elif prop_name == "items" and klass in ['GtkComboBox',
-                                                    'GtkComboBoxEntry']:
-                self._convert_combobox_items(node, prop)
-            elif prop_name == "text" and klass == 'GtkTextView':
-                self._convert_textview_text(prop)
-
-    def _remove_window(self, node):
-        object_node = get_object_node(get_child_nodes(node)[0])
-        parent = node.parentNode
-        parent.removeChild(node)
-        parent.appendChild(object_node)
-
-    def _convert_menu(self, node, popup=False):
-        if node.hasAttribute('constructor'):
-            return
-
-        uimgr = self._create_root_object('GtkUIManager',
-                                         template='uimanager')
-
-        if popup:
-            name = 'popup'
-        else:
-            name = 'menubar'
-
-        menu = self._dom.createElement(name)
-        menu.setAttribute('name', node.getAttribute('id'))
-        node.setAttribute('constructor', uimgr.getAttribute('id'))
-
-        for child in get_child_nodes(node):
-            obj_node = get_object_node(child)
-            item = self._convert_menuitem(uimgr, obj_node)
-            menu.appendChild(item)
-            child.removeChild(obj_node)
-            child.parentNode.removeChild(child)
-
-        ui = self._dom.createElement('ui')
-        uimgr.appendChild(ui)
-
-        ui.appendChild(menu)
-
-    def _convert_menuitem(self, uimgr, obj_node):
-        children = get_child_nodes(obj_node)
-        name = 'menuitem'
-        if children:
-            child_node = children[0]
-            menu_node = get_object_node(child_node)
-            # Can be GtkImage, which will take care of later.
-            if menu_node.getAttribute('class') == 'GtkMenu':
-                name = 'menu'
-
-        object_class = obj_node.getAttribute('class')
-        if object_class in ['GtkMenuItem',
-                            'GtkImageMenuItem',
-                            'GtkCheckMenuItem',
-                            'GtkRadioMenuItem']:
-            menu = self._dom.createElement(name)
-        elif object_class == 'GtkSeparatorMenuItem':
-            return self._dom.createElement('separator')
-        else:
-            raise NotImplementedError(object_class)
-
-        menu.setAttribute('action', obj_node.getAttribute('id'))
-        self._add_action_from_menuitem(uimgr, obj_node)
-        if children:
-            for child in get_child_nodes(menu_node):
-                obj_node = get_object_node(child)
-                item = self._convert_menuitem(uimgr, obj_node)
-                menu.appendChild(item)
-                child.removeChild(obj_node)
-                child.parentNode.removeChild(child)
-        return menu
-
-    def _menuitem_to_action(self, node, properties):
-        copy_properties(node, ['label', 'tooltip'], properties)
-
-    def _togglemenuitem_to_action(self, node, properties):
-        self._menuitem_to_action(node, properties)
-        copy_properties(node, ['active'], properties)
-
-    def _radiomenuitem_to_action(self, node, properties):
-        self._togglemenuitem_to_action(node, properties)
-        copy_properties(node, ['group'], properties)
-
-    def _add_action_from_menuitem(self, uimgr, node):
-        properties = {}
-        object_class = node.getAttribute('class')
-        object_id = node.getAttribute('id')
-        if object_class == 'GtkMenuItem':
-            name = 'GtkAction'
-            self._menuitem_to_action(node, properties)
-        elif object_class == 'GtkCheckMenuItem':
-            name = 'GtkToggleAction'
-            self._togglemenuitem_to_action(node, properties)
-        elif object_class == 'GtkRadioMenuItem':
-            name = 'GtkRadioAction'
-            self._radiomenuitem_to_action(node, properties)
-        elif object_class == 'GtkImageMenuItem':
-            name = 'GtkAction'
-            children = get_child_nodes(node)
-            if (children and
-                children[0].getAttribute('internal-child') == 'image'):
-                image = get_object_node(children[0])
-                child = get_property_node(image, 'stock')
-                if child is not None:
-                    properties['stock_id'] = child
-            self._menuitem_to_action(node, properties)
-        elif object_class == 'GtkSeparatorMenuItem':
-            return
-        else:
-            raise NotImplementedError(object_class)
-
-        if get_property(node, 'use_stock') == 'True':
-            if 'label' in properties:
-                properties['stock_id'] = properties['label']
-                del properties['label']
-
-        properties['name'] = object_id
-        action = self._create_object(name,
-                                     object_id,
-                                     properties=properties)
-        for signal in get_signal_nodes(node):
-            signal_name = signal.getAttribute('name')
-            if signal_name in ['activate', 'toggled']:
-                action.appendChild(signal)
-            else:
-                print 'Unhandled signal %s::%s' % (node.getAttribute('class'),
-                                                   signal_name)
-
-        if not uimgr.childNodes:
-            child = self._dom.createElement('child')
-            uimgr.appendChild(child)
-
-            group = self._create_object('GtkActionGroup', None,
-                                        template='actiongroup')
-            child.appendChild(group)
-        else:
-            group = uimgr.childNodes[0].childNodes[0]
-
-        child = self._dom.createElement('child')
-        group.appendChild(child)
-        child.appendChild(action)
-
-        for accelerator in get_accelerator_nodes(node):
-            signal_name = accelerator.getAttribute('signal')
-            if signal_name != 'activate':
-                print 'Unhandled accelerator signal for %s::%s' % (
-                    node.getAttribute('class'), signal_name)
-                continue
-            accelerator.removeAttribute('signal')
-            child.appendChild(accelerator)
-
-    def _convert_sizegroup(self, node, prop):
-        # This is Gazpacho only
-        node.removeChild(prop)
-        obj = self._get_object(prop.childNodes[0].data)
-        if obj is None:
-            widgets = self._get_objects_by_attr("class", "GtkSizeGroup")
-            if widgets:
-                obj = widgets[-1]
-            else:
-                obj = self._create_root_object('GtkSizeGroup',
-                                               template='sizegroup')
-
-        widgets = obj.getElementsByTagName("widgets")
-        if widgets:
-            assert len(widgets) == 1
-            widgets = widgets[0]
-        else:
-            widgets = self._dom.createElement("widgets")
-            obj.appendChild(widgets)
-
-        member = self._dom.createElement("widget")
-        member.setAttribute("name", node.getAttribute("id"))
-        widgets.appendChild(member)
-
-    def _convert_dialog_response(self, node, object_name, response):
-        # 1) Get parent dialog node
-        while True:
-            # If we can't find the parent dialog, give up
-            if node == self._dom:
-                return
-
-            if (node.tagName == 'object' and
-                node.getAttribute('class') in DIALOGS):
-                dialog = node
-                break
-            node = node.parentNode
-            assert node
-
-        # 2) Get dialogs action-widgets tag, create if not found
-        for child in dialog.childNodes:
-            if child.nodeType != Node.ELEMENT_NODE:
-                continue
-            if child.tagName == 'action-widgets':
-                actions = child
-                break
-        else:
-            actions = self._dom.createElement("action-widgets")
-            dialog.appendChild(actions)
-
-        # 3) Add action-widget tag for the response
-        action = self._dom.createElement("action-widget")
-        action.setAttribute("response", response)
-        action.appendChild(self._dom.createTextNode(object_name))
-        actions.appendChild(action)
-
-    def _convert_adjustment(self, prop):
-        properties = {}
-        if prop.childNodes:
-            data = prop.childNodes[0].data
-            value, lower, upper, step, page, page_size = data.split(' ')
-            properties.update(value=value,
-                              lower=lower,
-                              upper=upper,
-                              step_increment=step,
-                              page_increment=page,
-                              page_size=page_size)
-        else:
-            prop.appendChild(self._dom.createTextNode(""))
-
-        adj = self._create_root_object("GtkAdjustment",
-                                       template='adjustment',
-                                       properties=properties)
-        prop.childNodes[0].data = adj.getAttribute('id')
-
-    def _convert_combobox_items(self, node, prop):
-        parent = prop.parentNode
-        if not prop.childNodes:
-            parent.removeChild(prop)
-            return
-
-        translatable_attr = prop.attributes.get('translatable')
-        translatable = translatable_attr is not None and translatable_attr.value == 'yes'
-        has_context_attr = prop.attributes.get('context')
-        has_context = has_context_attr is not None and has_context_attr.value == 'yes'
-        comments_attr = prop.attributes.get('comments')
-        comments = comments_attr is not None and comments_attr.value or None
-
-        value = prop.childNodes[0].data
-        model = self._create_root_object("GtkListStore",
-                                         template="model")
-
-        columns = self._dom.createElement('columns')
-        model.appendChild(columns)
-
-        column = self._dom.createElement('column')
-        column.setAttribute('type', 'gchararray')
-        columns.appendChild(column)
-
-        data = self._dom.createElement('data')
-        model.appendChild(data)
-
-        if value.endswith('\n'):
-            value = value[:-1]
-        for item in value.split('\n'):
-            row = self._dom.createElement('row')
-            data.appendChild(row)
-
-            col = self._dom.createElement('col')
-            col.setAttribute('id', '0')
-            if translatable:
-                col.setAttribute('translatable', 'yes')
-            if has_context:
-                splitting = item.split('|', 1)
-                if len(splitting) == 2:
-                    context, item = splitting
-                    col.setAttribute('context', context)
-            if comments is not None:
-                col.setAttribute('comments', comments)
-            col.appendChild(self._dom.createTextNode(item))
-            row.appendChild(col)
-
-        model_prop = self._dom.createElement('property')
-        model_prop.setAttribute('name', 'model')
-        model_prop.appendChild(
-            self._dom.createTextNode(model.getAttribute('id')))
-        parent.appendChild(model_prop)
-
-        parent.removeChild(prop)
-
-        child = self._dom.createElement('child')
-        node.appendChild(child)
-        cell_renderer = self._create_object('GtkCellRendererText', None,
-                                            template='renderer')
-        child.appendChild(cell_renderer)
-
-        attributes = self._dom.createElement('attributes')
-        child.appendChild(attributes)
-
-        attribute = self._dom.createElement('attribute')
-        attributes.appendChild(attribute)
-        attribute.setAttribute('name', 'text')
-        attribute.appendChild(self._dom.createTextNode('0'))
-
-    def _convert_textview_text(self, prop):
-        if not prop.childNodes:
-            prop.parentNode.removeChild(prop)
-            return
-
-        data = prop.childNodes[0].data
-        if prop.hasAttribute('translatable'):
-            prop.removeAttribute('translatable')
-        tbuffer = self._create_root_object("GtkTextBuffer",
-                                           template='textbuffer',
-                                           properties=dict(text=data))
-        prop.childNodes[0].data = tbuffer.getAttribute('id')
-        prop.setAttribute('name', 'buffer')
-
-    def _packing_prop_to_child_attr(self, node, prop_name, prop_val,
-                                   attr_val=None):
-        for child in get_child_nodes(node):
-            packing_props = [p for p in child.childNodes if p.nodeName == "packing"]
-            if not packing_props:
-                continue
-            assert len(packing_props) == 1
-            packing_prop = packing_props[0]
-            properties = packing_prop.getElementsByTagName("property")
-            for prop in properties:
-                if (prop.getAttribute("name") != prop_name or
-                    prop.childNodes[0].data != prop_val):
-                    continue
-                packing_prop.removeChild(prop)
-                child.setAttribute(prop_name, attr_val or prop_val)
-            if len(properties) == 1:
-                child.removeChild(packing_prop)
-
-    def _convert_ui(self, node):
-        cdata = node.childNodes[0]
-        data = cdata.toxml().strip()
-        if not data.startswith("<![CDATA[") or not data.endswith("]]>"):
-            return
-        data = data[9:-3]
-        child = minidom.parseString(data).childNodes[0]
-        nodes = child.childNodes[:]
-        for child_node in nodes:
-            node.appendChild(child_node)
-        node.removeChild(cdata)
-        if not node.hasAttribute("id"):
-            return
-
-        # Updating references made by widgets
-        parent_id = node.parentNode.getAttribute("id")
-        for widget in self._get_objects_by_attr("constructor",
-                                                node.getAttribute("id")):
-            widget.getAttributeNode("constructor").value = parent_id
-        node.removeAttribute("id")
-
-    def _convert_accessibility(self, node):
-        objectNode = node.parentNode
-        parent_id = objectNode.getAttribute("id")
-
-        properties = {}
-        for node in node.childNodes:
-            if node.nodeName == 'atkproperty':
-                node.tagName = 'property'
-                properties[node.getAttribute('name')] = node
-                node.parentNode.removeChild(node)
-            elif node.nodeName == 'atkrelation':
-                node.tagName = 'relation'
-                relation_type = node.getAttribute('type')
-                relation_type = relation_type.replace('_', '-')
-                node.setAttribute('type', relation_type)
-            elif node.nodeName == 'atkaction':
-                node.tagName = 'action'
-
-        if properties:
-            child = self._dom.createElement('child')
-            child.setAttribute("internal-child", "accessible")
-
-            atkobject = self._create_object(
-                "AtkObject", None,
-                template='a11y-%s' % (parent_id,),
-                properties=properties)
-            child.appendChild(atkobject)
-            objectNode.appendChild(child)
-
-    def _strip_root(self, root_name):
-        for widget in self._dom.getElementsByTagName("widget"):
-            if widget.getAttribute('id') == root_name:
-                break
-        else:
-            raise SystemExit("Could not find an object called `%s'" % (
-                root_name))
-
-        for child in self._interface.childNodes[:]:
-            if child.nodeType != Node.ELEMENT_NODE:
-                continue
-            child.parentNode.removeChild(child)
-
-        self._interface.appendChild(widget)
-
-
-def _indent(output):
-    if not subprocess:
-        return output
-
-    for directory in os.environ['PATH'].split(os.pathsep):
-        filename = os.path.join(directory, 'xmllint')
-        if os.path.exists(filename):
-            break
-    else:
-        return output
-
-    s = subprocess.Popen([filename, '--format', '-'],
-                         stdin=subprocess.PIPE,
-                         stdout=subprocess.PIPE)
-    s.stdin.write(output)
-    s.stdin.close()
-    return s.stdout.read()
-
-def usage():
-    print __doc__
-
-def main(args):
-    try:
-        opts, args = getopt.getopt(args[1:], "hwr:",
-                                   ["help", "skip-windows", "root="])
-    except getopt.GetoptError:
-        usage()
-        return 2
-
-    if len(args) != 2:
-        usage()
-        return 2
-
-    input_filename, output_filename = args
-
-    skip_windows = False
-    split = False
-    root = None
-    for o, a in opts:
-        if o in ("-h", "--help"):
-            usage()
-            sys.exit()
-        elif o in ("-r", "--root"):
-            root = a
-        elif o in ("-w", "--skip-windows"):
-            skip_windows = True
-
-    conv = GtkBuilderConverter(skip_windows=skip_windows,
-                               root=root)
-    conv.parse_file(input_filename)
-
-    xml = _indent(conv.to_xml())
-    if output_filename == "-":
-        print xml
-    else:
-        open(output_filename, 'w').write(xml)
-        print "Wrote", output_filename
-
-    return 0
-
-if __name__ == "__main__":
-    sys.exit(main(sys.argv))
index 72c2029f2b1486a77b642cefff94b8f9807e7ee6..eb078f98f4fb7a41e16f245ea0edc8b4fa311bf7 100644 (file)
@@ -184,7 +184,7 @@ endif
 # install-data-am, and not install-exec-am. We need to ensure this gets run
 # after the libraries are installed in their final locations.
 install-data-hook:
-       @if $(RUN_QUERY_IMMODULES_TEST) ; then \
+       $(AM_V_GEN) if $(RUN_QUERY_IMMODULES_TEST) ; then \
          echo $(mkinstalldirs) $(DESTDIR)$(libdir)/gtk-3.0/3.0.0 ; \
          $(mkinstalldirs) $(DESTDIR)$(libdir)/gtk-3.0/3.0.0 ; \
          echo "$(top_builddir)/gtk/gtk-query-immodules-3.0 > $(DESTDIR)$(libdir)/gtk-3.0/3.0.0/immodules.cache" ; \
@@ -236,7 +236,7 @@ noinst_LTLIBRARIES =                                \
 included-modules: $(noinst_LTLIBRARIES)
 
 immodules.cache: Makefile.am $(module_LTLIBRARIES)
-       $(top_builddir)/gtk/gtk-query-immodules-3.0 $(module_LTLIBRARIES) > immodules.cache
+       $(AM_V_GEN) $(top_builddir)/gtk/gtk-query-immodules-3.0 $(module_LTLIBRARIES) > immodules.cache
 
 EXTRA_DIST += README.multipress